package rm.ep.server;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Properties;

import rm.ep.shared.LogEntity;
import rm.ep.shared.EntityExistsException;
import rm.ep.shared.SubscriberEntity;

import com.googlecode.objectify.Key;
import com.googlecode.objectify.Objectify;

public class SubscriberDAO extends BaseDAO {

	static {
		Properties properties = new Properties();
		InputStream is = null;
		try {
			is = ClassLoader.getSystemResourceAsStream("rm/ep/server/SubscriberDAO.properties");
		    properties.load(is);
		    is.close();
		} catch (IOException e) {
			throw new IllegalArgumentException(e);
		} 
		S_NEW_SUBJECT = properties.getProperty("subscriber.new.subject");
		S_NEW_BODY = properties.getProperty("subscriber.new.body");
		S_DEACTIVATED_SUBJECT = properties.getProperty("subscriber.deactivated.subject");
		S_DEACTIVATED_BODY = properties.getProperty("subscriber.deactivated.body");
		S_REACTIVATED_SUBJECT = properties.getProperty("subscriber.reactivated.subject");
		S_REACTIVATED_BODY = properties.getProperty("subscriber.reactivated.body");
		S_RESETPWD_SUBJECT = properties.getProperty("subscriber.resetpwd.subject");
		S_RESETPWD_BODY = properties.getProperty("subscriber.resetpwd.body");
		S_KEYWORDS_SUBJECT = properties.getProperty("subscriber.keywords.subject");
		S_KEYWORDS_BODY = properties.getProperty("subscriber.keywords.body");
		S_PURGE_SUBJECT = properties.getProperty("subscriber.purge.subject");
		S_PURGE_BODY = properties.getProperty("subscriber.purge.body");
		properties.clear();
	}
	
	
	public SubscriberEntity insert(String email, List<String> keywords) 
			throws EntityExistsException {

		final String emailLower = email.toLowerCase();
		SubscriberEntity se = ofy().query(SubscriberEntity.class).filter("fEmail", emailLower).get();
		if (se != null) throw new EntityExistsException(email);
		
		final SubscriberEntity e = new SubscriberEntity(email);
		e.setKeywords(keywords);
		ofy().put(e); // no logging -> could be bogus
		sendEmail(email, EMAIL_ADDRESS_NOREPLY, S_NEW_SUBJECT, S_NEW_BODY);
		return e;
		
	}
	
	public SubscriberEntity deActivate(Long id) {
		final SubscriberEntity e = ofy().get(SubscriberEntity.class, id);
		e.setActive(Boolean.FALSE);
		transact(new Transactable() {
			@Override
			public void execute(Objectify ofy) {
				com.google.appengine.api.datastore.Key key = Key.raw(ofy.put(e));
				ofy.put(new LogEntity(getOperator(e.getEmail()), "De-Activated", key));
			}
		});
		sendEmail(e.getEmail(), EMAIL_ADDRESS_NOREPLY, S_DEACTIVATED_SUBJECT, S_DEACTIVATED_BODY);
		return e;
	}
	
	public SubscriberEntity reActivate(Long id) {
		final SubscriberEntity e = ofy().get(SubscriberEntity.class, id);
		e.setActive(Boolean.TRUE);
		transact(new Transactable() {
			@Override
			public void execute(Objectify ofy) {
				com.google.appengine.api.datastore.Key key = Key.raw(ofy.put(e));
				ofy.put(new LogEntity(getOperator(e.getEmail()), "Re-Activated", key));
			}
		});
		sendEmail(e.getEmail(), EMAIL_ADDRESS_NOREPLY, S_REACTIVATED_SUBJECT, S_REACTIVATED_BODY);
		return e;
	}
	
	public List<SubscriberEntity> selectActive() {
		return ofy().query(SubscriberEntity.class).filter("fIsActive", true).list();
	}

	public List<SubscriberEntity> selectInActive() {
		return ofy().query(SubscriberEntity.class).filter("fIsActive", false).list();
	}

	public Integer resetPassword(Long id) {
		final SubscriberEntity e = ofy().get(SubscriberEntity.class, id);
		e.resetPassword();
		transact(new Transactable() {
			@Override
			public void execute(Objectify ofy) {
				com.google.appengine.api.datastore.Key key = Key.raw(ofy.put(e));
				ofy.put(new LogEntity(getOperator(e.getEmail()), "Password reseted", key));
			}
		});
		sendEmail(e.getEmail(), EMAIL_ADDRESS_NOREPLY, S_RESETPWD_SUBJECT, S_RESETPWD_BODY);
		return e.getPassword();
	}
	
	public Boolean verifyPassword(Long id, Integer password) {
		final SubscriberEntity e = ofy().get(SubscriberEntity.class, id);
		return (e.getPassword().equals(password));
	}

	public SubscriberEntity setKeywords(Long id, final List<String> keywords) { 
		final SubscriberEntity e = ofy().get(SubscriberEntity.class, id);
		if (!e.isActive()) {
			throw new IllegalStateException("Subscriber must be active");
		}
		e.setKeywords(keywords);
		final String comment = join("New Keywords : ", keywords);
		transact(new Transactable() {
			@Override
			public void execute(Objectify ofy) {
				com.google.appengine.api.datastore.Key key = Key.raw(ofy.put(e));
				ofy.put(new LogEntity(getOperator(e.getEmail()), comment, key));
			}
		});
		return e;
	}
	
	public void purgeNewSubscribers() {
		
		long week1 = System.currentTimeMillis() - 1000*60*60*24*7;
		long week2 = week1 * 2;
		
		List<SubscriberEntity> l = ofy().query(SubscriberEntity.class)
										.filter("fIsActive", Boolean.FALSE)
										.filter("fModifiedAt < ", week1)
										.list();
		
		for (SubscriberEntity e : l) {
			int cnt = ofy().query(LogEntity.class).ancestor(e).count();
			if (cnt == 0) { // never activated !
				if (e.getLastModifiedTime() < week2) {
					// too long, has been informed already so delete
					ofy().delete(e);
				} else {
					// TODO sendEmail()
				}
			}
		}
		
	}
	
	
	protected static String S_NEW_SUBJECT, S_NEW_BODY,
							S_DEACTIVATED_SUBJECT, S_DEACTIVATED_BODY,
							S_REACTIVATED_SUBJECT, S_REACTIVATED_BODY,
							S_RESETPWD_SUBJECT, S_RESETPWD_BODY,
							S_KEYWORDS_SUBJECT, S_KEYWORDS_BODY,
							S_PURGE_SUBJECT, S_PURGE_BODY;

}
